﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;

namespace Core.Editor
{
    public static class ScriptHelper
    {
        private static readonly Dictionary<string, string> Scripts = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

        static ScriptHelper()
        {
            Scripts.Clear();
            foreach (var path in AssetDatabase.GetAllAssetPaths())
            {
                if (path.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
                {
                    var fileName = Path.GetFileNameWithoutExtension(path);
                    if (!string.IsNullOrEmpty(fileName) && !Scripts.ContainsKey(fileName))
                    {
                        Scripts[fileName] = path;
                    }
                }
            }
        }

        private static string GetScriptShortName(string name)
        {
            var segments = name.Split('.');
            return segments.Length > 0 ? segments[^1] : name;
        }

        public static bool IsExistScript(string name)
        {
            return Scripts.ContainsKey(name) || Scripts.ContainsKey(GetScriptShortName(name));
        }

        public static void OpenScript(string name)
        {
            var shortName = GetScriptShortName(name);
            if (!Scripts.TryGetValue(shortName, out var path))
            {
                Debug.LogError($"打开脚本文件失败：没有找到 {name} 脚本文件！");
                return;
            }

            var monoScript = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
            if (monoScript)
            {
                AssetDatabase.OpenAsset(monoScript);
            }
            else
            {
                Debug.LogError($"打开脚本文件失败：没有找到 {name} 脚本文件！");
            }
        }

        public static void OpenScript(string name, int lineNumber)
        {
            var shortName = GetScriptShortName(name);
            if (!Scripts.TryGetValue(shortName, out var path))
            {
                Debug.LogError($"打开脚本文件失败：没有找到 {name} 脚本文件！");
                return;
            }

            var monoScript = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
            if (monoScript)
            {
                AssetDatabase.OpenAsset(monoScript, lineNumber);
            }
            else
            {
                Debug.LogError($"打开脚本文件失败：没有找到 {name} 脚本文件！");
            }
        }

        public static string CreateScriptFormTemplate(string fullPath, string scriptType, string templateName, params string[] replace)
        {
            if (!Directory.Exists(fullPath)) fullPath = Application.dataPath;

            var path = EditorUtility.SaveFilePanel("Create " + scriptType + " Class", fullPath, "New" + scriptType,
                "cs");
            if (string.IsNullOrEmpty(path)) return "<None>";

            if (!path.StartsWith(Application.dataPath, StringComparison.OrdinalIgnoreCase))
            {
                Debug.LogError($"新建 {scriptType} 失败：创建路径必须在当前项目的 Assets 路径下！");
                return "<None>";
            }

            var className = Path.GetFileNameWithoutExtension(path);
            if (File.Exists(path))
            {
                Debug.LogError($"新建 {scriptType} 失败：已存在类文件 {className}");
                return "<None>";
            }

            var asset = Resources.Load<TextAsset>($"Template/{templateName}");
            if (!asset)
            {
                Debug.LogError($"新建 {scriptType} 失败：丢失脚本模板文件！");
                return "<None>";
            }
            var codeBuilder = new StringBuilder(asset.text).Replace("#SCRIPTNAME#", className);
            if (replace != null)
            {
                foreach (var tag in replace)
                {
                    codeBuilder.Replace(tag, className);
                }
            }
            try
            {
                File.WriteAllText(path, codeBuilder.ToString(), Encoding.UTF8);
            }
            catch (IOException ex)
            {
                Debug.LogError($"文件写入失败: {ex.Message}");
                return "<None>";
            }
            AssetDatabase.Refresh();
            var assetPath = path.Substring(path.IndexOf("Assets", StringComparison.Ordinal));
            var csFile = AssetDatabase.LoadAssetAtPath<TextAsset>(assetPath);
            if (csFile)
            {
                EditorGUIUtility.PingObject(csFile);
                Selection.activeObject = csFile;
            }
            return className;
        }
    }
}